import 'dart:core';
import 'package:atlassian_apis/jira_platform.dart';
import 'package:flutter/material.dart';

class ProgramUtils {
  static Map<String, Duration> calculateTotalTime(
      Map<String, List<DateTimeRange>> activePrograms) {
    Map<String, Duration> totalTimePerProgram = {};

    activePrograms.forEach((program, dateRanges) {
      Duration totalDuration = Duration.zero;

      for (var dateRange in dateRanges) {
        Duration difference = dateRange.end.difference(dateRange.start);
        totalDuration += difference;
      }

      totalTimePerProgram[program] = totalDuration;
    });

    return totalTimePerProgram;
  }

  static Map<String, int> calculatePercentageOfWork(
      Map<String, Duration> totalTimePerActiveProgram,
      Map<String, Duration> totalTimePerAllProgram) {
    Map<String, int> percentageOfWork = {};

    totalTimePerActiveProgram.forEach((program, activeTime) {
      Duration allTime = totalTimePerAllProgram[program] ?? Duration.zero;

      int percentage =
          ((activeTime.inSeconds / allTime.inSeconds) * 100).round();

      percentageOfWork[program] = percentage;
    });

    return percentageOfWork;
  }

  static Map<String, List<(DateTimeRange, int)>> mergeData(
      Map<String, List<DateTimeRange>> activePrograms,
      Map<String, List<DateTimeRange>> allPrograms) {
    Map<String, Duration> totalTimePerActiveProgram =
        calculateTotalTime(activePrograms);
    Map<String, Duration> totalTimePerAllProgram =
        calculateTotalTime(allPrograms);
    Map<String, int> percentageOfWork = calculatePercentageOfWork(
        totalTimePerActiveProgram, totalTimePerAllProgram);

    Map<String, List<(DateTimeRange, int)>> merged = {};

    allPrograms.forEach((program, ranges) {
      List<(DateTimeRange, int)> mergedList = [];
      ranges.forEach((range) {
        mergedList.add((range, percentageOfWork[program] ?? 0));
      });
      merged[program] = mergedList;
    });

    return merged;
  }
}

/// Функция для получения списка проектов и связанных с ними задач из Jira.
///
/// [userEmail] - email пользователя.
/// [userApiKey] - ключ API пользователя.
/// [userDomain] - домен пользователя.
///
/// Возвращает [Map], в котором ключ - это название проекта в формате "projectKey : projectName",
/// а значение - список задач с их ключами и названиями.
Future<Map<String, List<Map<String, String>>>> getProjects(
    String userEmail, String userApiKey, String userDomain) async {
  var user = userEmail;
  var apiToken = userApiKey;

  var client = ApiClient.basicAuthentication(
      Uri.https('$userDomain.atlassian.net', ''),
      user: user,
      apiToken: apiToken);

  var jira = JiraPlatformApi(client);

  try {
    var res = await jira.projects.searchProjects();

    var projects = res.values;
    var projectTasks = <String, List<Map<String, String>>>{};
    for (var project in projects) {
      var projectKey = project.key.toString();
      var res = await jira.issueSearch.searchForIssuesUsingJql(
        jql: 'project=$projectKey',
      );
      var issues = res.issues;
      var taskList = <Map<String, String>>[];
      for (var issue in issues) {
        print(issue.fields);
        var taskKey = issue.key!.toString();
        var taskName = issue.fields!["summary"]!.toString();
        var task = {"task_key": taskKey, "task_name": taskName};
        taskList.add(task);
      }
      projectTasks["$projectKey : ${project.name}"] = taskList;
    }
    return projectTasks;
  } catch (e) {
    print('Произошла ошибка: $e');
    return {};
  } finally {
    client.close();
  }
}

/// Функция для добавления времени к задаче в Jira.
///
/// [userEmail] - email пользователя.
/// [userApiKey] - ключ API пользователя.
/// [userDomain] - домен пользователя.
/// [taskKey] - ключ задачи.
/// [time] - время в формате "1d 2h 3m".
Future<void> addTime(String userEmail, String userApiKey, String userDomain,
    String taskKey, String time) async {
  var user = userEmail;
  var apiToken = userApiKey;

  var client = ApiClient.basicAuthentication(
      Uri.https('$userDomain.atlassian.net', ''),
      user: user,
      apiToken: apiToken);

  var jiraIssueWorklog = IssueWorklogsApi(client);

  Worklog worklog = Worklog(timeSpent: time);

  try {
    await jiraIssueWorklog.addWorklog(issueIdOrKey: taskKey, body: worklog);
  } catch (e) {
    print('Произошла ошибка: $e');
  } finally {
    client.close();
  }
}

/// Функция для форматирования объекта [Duration] в строку в формате "1d 2h 3m".
///
/// [duration] - объект Duration.
///
/// Возвращает отформатированную строку времени.
String formatDuration(Duration duration) {
  String days = duration.inDays == 0 ? '' : '${duration.inDays}d ';
  String hours = duration.inHours.remainder(24) == 0
      ? ''
      : '${duration.inHours.remainder(24)}h ';
  String minutes = duration.inMinutes.remainder(60) == 0
      ? ''
      : '${duration.inMinutes.remainder(60)}m';

  return '$days$hours$minutes'.trim();
}
